package org.jeecg.weixin.web.controller;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.weixin.common.error.WxErrorException;
import org.jeecg.weixin.common.error.WxRuntimeException;
import org.jeecg.weixin.cp.api.WxCpOaService;
import org.jeecg.weixin.cp.api.WxCpService;
import org.jeecg.weixin.cp.api.impl.WxCpOaServiceImpl;
import org.jeecg.weixin.cp.bean.oa.WxCpCheckinDayData;
import org.jeecg.weixin.cp.bean.oa.WxCpCheckinMonthData;
import org.jeecg.weixin.cp.bean.oa.WxCpVacationConf;
import org.jeecg.weixin.web.config.WxCpConfiguration;
import org.jeecg.weixin.web.dto.WxCpOaMonthDataDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@RestController
@RequestMapping("/wx/cp/oa")
@Api(tags="企业微信")
public class WxCpOaController {
	
	@Autowired
	private ISysUserService sysUserService;
	
	/**
     * 获取打卡日报表
     *
     * @param jeecgDemo
     * @param pageNo
     * @param pageSize
     * @param req
	 * @return 
     * @return
	 * @throws WxErrorException 
     */
    @ApiOperation(value = "获取打卡日报表", notes = "获取打卡日报表")
    @PostMapping(value = "/getCheckinDayData")
    public Result<Object> getCheckinDayData(
    		@ApiParam(name = "startTime", value = "开始时间", required = true) @DateTimeFormat(pattern="yyyy-MM-dd") @RequestParam(value = "startTime", required = true) Date startTime,
    		@ApiParam(name = "endTime", value = "结束时间", required = true) @DateTimeFormat(pattern="yyyy-MM-dd") @RequestParam(value = "endTime", required = true) Date endTime,
    		@ApiParam(name = "userIdList", value = "用户列表", required = true) @RequestParam(value = "userIdList", required = true) String userIds) throws WxErrorException{
    	if(userIds != null && !"".equals(userIds)){
    		String userIdsArr[] = userIds.split(",");
        	WxCpService wxCpService =  WxCpConfiguration.getCpService(3010011);
        	WxCpOaService wxCpOaService = new WxCpOaServiceImpl(wxCpService);
        	List<WxCpCheckinDayData> result = wxCpOaService.getCheckinDayData(startTime, endTime, Arrays.asList(userIdsArr));
			Map<String, List<WxCpCheckinDayData>> map = result.stream()
					.collect(Collectors.groupingBy(value -> MessageFormat.format("{0}#{1}",
							value.getBaseInfo().getAcctid(), value.getBaseInfo().getDate())));
			
			
			Calendar month = Calendar.getInstance();
			month.set(2021, 1-1, 1);
			int maxDay = month.getActualMaximum(Calendar.DAY_OF_MONTH);
			int minDay = month.getActualMinimum(Calendar.DAY_OF_MONTH);
			List<Map<String,String>> aaaaa = new ArrayList<>();
			for(String userId : userIdsArr){
				Map<String,String> data = new HashMap<>();
				data.put("userId", userId);
				//遍历当月所有天
				for (int i = minDay; i <= maxDay; i++) {
					month.set(2021, 1-1, i,0,0,0);
					long day = month.getTimeInMillis()/1000L;
					List<WxCpCheckinDayData> dayDatas = map.get(userId + "#" + day);
					if(CollectionUtils.isEmpty(dayDatas)){
						data.put("day_"+i, "");
					}else{
						WxCpCheckinDayData dayData = dayDatas.get(0);
						data.put("name", dayData.getBaseInfo().getName());
						data.put("departsName", dayData.getBaseInfo().getDepartsName());
						data.put("day_"+i, dayData.getToText());
					}
				}
				
				aaaaa.add(data);
			}
			return Result.OK(aaaaa);
    	}else {
    		throw new WxRuntimeException("用户列表不能为空");
    	}
    }
    
    /**
     * 获取打卡日报表
     *
     * @param jeecgDemo
     * @param pageNo
     * @param pageSize
     * @param req
	 * @return 
     * @return
	 * @throws WxErrorException 
     */
    @ApiOperation(value = "获取打卡日报表", notes = "获取打卡日报表")
    @PostMapping(value = "/getAllCheckinDayData" ,produces = "application/json")
    public Result<Object> getAllCheckinDayData(
    		@ApiParam(name = "year", value = "年份", required = true) @RequestParam(value = "year", required = true) Integer year,
    		@ApiParam(name = "month", value = "月份", required = true) @RequestParam(value = "month", required = true) Integer month) throws WxErrorException{
    	List<String> ignores = Arrays.asList("admin","admin2","admin3","admin4","18695887213","test22","jeecg","zhagnxiao");
    	List<String> ids = sysUserService.getUsernamesWithIngore(ignores);
    	// List<String> ids = new ArrayList<String>();
    	// ids.add("wangzhen");
    	if(ids != null && !ids.isEmpty()){
        	WxCpService wxCpService =  WxCpConfiguration.getCpService(3010011);
        	WxCpOaService wxCpOaService = new WxCpOaServiceImpl(wxCpService);
        	Calendar startTime = Calendar.getInstance();
        	Calendar endTime = Calendar.getInstance();
        	startTime.set(year, month-1, 1);
        	endTime.set(year, month-1, startTime.getActualMaximum(Calendar.DAY_OF_MONTH));
        	List<WxCpCheckinDayData> result = wxCpOaService.getCheckinDayData(startTime.getTime(), endTime.getTime(), ids);
        	
			Map<String, List<WxCpCheckinDayData>> map = result.stream()
					.collect(Collectors.groupingBy(value -> MessageFormat.format("{0}#{1}",
							value.getBaseInfo().getAcctid().toLowerCase(), value.getBaseInfo().getDate().toString())));
			
			Calendar monthCd = Calendar.getInstance();
			monthCd.set(year, month-1, 1);
			int maxDay = monthCd.getActualMaximum(Calendar.DAY_OF_MONTH);
			int minDay = monthCd.getActualMinimum(Calendar.DAY_OF_MONTH);
			List<Map<String,String>> aaaaa = new ArrayList<>();
			for(String userId : ids){
				Map<String,String> data = new HashMap<>();
				data.put("userId", userId);
				//遍历当月所有天
				for (int i = minDay; i <= maxDay; i++) {
					monthCd.set(2021, month-1, i,0,0,0);
					long day = monthCd.getTimeInMillis()/1000L;
					List<WxCpCheckinDayData> dayDatas = map.get(userId.toLowerCase() + "#" + day);
					if(CollectionUtils.isEmpty(dayDatas)){
						data.put("day_"+i, "");
					}else{
						WxCpCheckinDayData dayData = dayDatas.get(0);
						data.put("name", dayData.getBaseInfo().getName());
						data.put("departsName", dayData.getBaseInfo().getDepartsName());
						data.put("day_"+i, dayData.getToText());
					}
				}
				
				aaaaa.add(data);
			}
			return Result.OK(aaaaa);
    	}else {
    		throw new WxRuntimeException("用户列表不能为空");
    	}
    }
    
    /**
     * 获取打卡日报表
     *
     * @param jeecgDemo
     * @param pageNo
     * @param pageSize
     * @param req
	 * @return 
     * @return
	 * @throws WxErrorException 
     */
    @ApiOperation(value = "获取打卡月报表", notes = "获取打卡月报表")
    @PostMapping(value = "/getCheckinMonthData")
    public Result<WxCpOaMonthDataDTO> getCheckinMonthData(
    		@ApiParam(name = "startTime", value = "开始时间", required = true) @DateTimeFormat(pattern="yyyy-MM-dd") @RequestParam(value = "startTime", required = true) Date startTime,
    		@ApiParam(name = "endTime", value = "结束时间", required = true) @DateTimeFormat(pattern="yyyy-MM-dd") @RequestParam(value = "endTime", required = true) Date endTime) throws WxErrorException{
    	List<String> ignores = Arrays.asList("admin","admin2","admin3","admin4","test22","jeecg","zhagnxiao");
    	List<String> userIds = sysUserService.getUsernamesWithIngore(ignores);
    	if(!CollectionUtils.isEmpty(userIds)){
    		//微信接口获取打卡月数据
        	WxCpService wxCpService =  WxCpConfiguration.getCpService(3010011);
        	WxCpOaService wxCpOaService = new WxCpOaServiceImpl(wxCpService);
        	List<WxCpCheckinMonthData> result = wxCpOaService.getCheckinMonthData(startTime, endTime, userIds);
        	
        	//微信接口获取请假类别
        	WxCpService wxCpServiceWf =  WxCpConfiguration.getCpService(3010040);
        	WxCpOaService wxCpOaServiceWf = new WxCpOaServiceImpl(wxCpServiceWf);
        	List<WxCpVacationConf> vacationConfs = wxCpOaServiceWf.getVacationConf();
        	
        	WxCpOaMonthDataDTO dto = new WxCpOaMonthDataDTO();
        	dto.setColumns(new ArrayList<WxCpOaMonthDataDTO.Column>());
        	dto.setDatas(new ArrayList<Map<String, Object>>());
        	
        	dto.initColumn(vacationConfs);
        	
        	for(WxCpCheckinMonthData monthData : result){
        		Map<String,Object> data = new HashMap<>();
        		data.put("acctid", monthData.getBaseInfo().getAcctid());//账户
        		data.put("name", monthData.getBaseInfo().getName());//姓名
        		data.put("departsName", monthData.getBaseInfo().getDepartsName());//部门名称
        		
        		data.put("workDays", monthData.getSummaryInfo().getWorkDays());//应出勤天数
        		data.put("regularDays", monthData.getSummaryInfo().getRegularDays());//正常天数
        		data.put("exceptDays", monthData.getSummaryInfo().getExceptDays());//异常天数
        		data.put("standardWorkSec", conversion2Hour(monthData.getSummaryInfo().getStandardWorkSec()));//标准工作时长
        		data.put("regularWorkSec", conversion2Hour(monthData.getSummaryInfo().getRegularWorkSec()));//实际工作时长
        		
        		// 迟到异常
        		int exception1Count = 0;
        		int exception1Time = 0;
        		// 早退异常
        		int exception2Count = 0;
        		int exception2Time = 0;
        		//缺卡异常
        		int exception3Count = 0;
        		//旷工异常
        		int exception4Count = 0;
        		int exception4Time = 0;
        		//地点异常
        		int exception5Count = 0;
        		//设备异常
        		int exception6Count = 0;
        		//累加异常考勤数据
        		if(monthData.getExceptionInfos() != null){
        			for(WxCpCheckinMonthData.ExceptionInfo exp : monthData.getExceptionInfos()){
						if(exp.getException() == 1L){
							exception1Count += exp.getCount();
							exception1Time += exp.getDuration();
						}else if(exp.getException() == 2L){
							exception2Count += exp.getCount();
							exception2Time += exp.getDuration();
						}else if(exp.getException() == 3L){
							exception3Count += exp.getCount();
						}else if(exp.getException() == 4L){
							exception4Count += exp.getCount();
							exception4Time += exp.getDuration();
						}else if(exp.getException() == 5L){
							exception5Count += exp.getCount();
						}else if(exp.getException() == 6L){
							exception6Count += exp.getCount();
						}
        			}
        		}
        		int exceptionCount = exception1Count + exception2Count + exception3Count + exception4Count + exception5Count + exception6Count;
        		data.put("exceptionCount", exceptionCount);//异常次数
        		data.put("exception1Count", exception1Count);//迟到次数
        		data.put("exception1Time", conversion2Min(exception1Time));//迟到时长
        		data.put("exception2Count", exception2Count);//早退次数
        		data.put("exception2Time", conversion2Min(exception2Time));//早退时长
        		data.put("exception3Count", exception3Count);//缺卡次数
        		data.put("exception4Count", exception4Count);//旷工次数
        		data.put("exception4Time", conversion2Min(exception4Time));//旷工时长
        		data.put("exception5Count", exception5Count);//地点异常次数
        		data.put("exception6Count", exception6Count);//设备异常次数
        		
        		//加班情况
        		data.put("workdayOverSec", conversion2Hour(monthData.getOverworkInfo().getWorkdayOverSec()));//工作日加班时长
        		data.put("holidaysOverSec", conversion2Hour(monthData.getOverworkInfo().getHolidaysOverSec()));//节假日加班时长
        		data.put("restdaysOverSec", conversion2Hour(monthData.getOverworkInfo().getRestdaysOverSec()));//休息日加班时长
        		//假勤信息
        		if(monthData.getSpItems() != null){
        			for(WxCpCheckinMonthData.SpItem spItem : monthData.getSpItems()){
        				//请假数据累计
        				if(spItem.getType() == 1L){
        					for(WxCpVacationConf conf : vacationConfs){
        						if(conf.getId() == spItem.getVacationId()){
        							data.put("column_"+conf.getId(), conversionByType(spItem.getDuration(),spItem.getTimeType()));
        						}
        	            	}
        				}else if(spItem.getType() == 2L){
        					data.put("spItem2Count", spItem.getCount());//补卡次数
        				}else if(spItem.getType() == 3L){
        					data.put("spItem3Count", conversionByType(spItem.getDuration(),spItem.getTimeType()));//出差时长
        				}else if(spItem.getType() == 4L){
        					data.put("spItem4Count", conversionByType(spItem.getDuration(),spItem.getTimeType()));//外出次数
        				}else if(spItem.getType() == 100L){
        					data.put("spItem100Count", spItem.getCount());//外勤次数
        				}
        			}
        		}
        		
        		dto.getDatas().add(data);
        	}
        	return Result.OK(dto);
    	}else {
    		throw new WxRuntimeException("用户列表不能为空");
    	}
    }
    
    private BigDecimal conversionByType(Long orgin, Long timeType){
    	if(timeType == 0L){
    		return conversion2Day(orgin);
    	}else{
    		return conversion2Hour(orgin);
    	}
    }
    
    private BigDecimal conversion2Min(Integer orgin){
    	if(orgin == null){
    		orgin = 0;
    	}
    	BigDecimal result = new BigDecimal(orgin);
    	result = result.divide(new BigDecimal(60),2,BigDecimal.ROUND_HALF_UP);
    	return result;
    }
    
    private BigDecimal conversion2Hour(Long orgin){
    	if(orgin == null){
    		orgin = 0L;
    	}
    	BigDecimal result = new BigDecimal(orgin);
    	result = result.divide(new BigDecimal(3600),2,BigDecimal.ROUND_HALF_UP);
    	return result;
    }
    
    private BigDecimal conversion2Hour(Integer orgin){
    	if(orgin == null){
    		orgin = 0;
    	}
    	BigDecimal result = new BigDecimal(orgin);
    	result = result.divide(new BigDecimal(3600),2,BigDecimal.ROUND_HALF_UP);
    	return result;
    }
    
    private BigDecimal conversion2Day(Long orgin){
    	if(orgin == null){
    		orgin = 0L;
    	}
    	BigDecimal result = new BigDecimal(orgin);
    	result = result.divide(new BigDecimal(86400),2,BigDecimal.ROUND_HALF_UP);
    	return result;
    }
    
}
